package baiduface

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

// FaceDetectResponse 人脸检测与属性分析响应结构
type FaceDetectResponse struct {
	ErrorCode int    `json:"error_code,omitempty"`
	ErrorMsg  string `json:"error_msg,omitempty"`
	FaceNum   int    `json:"face_num,omitempty"`
	FaceList  []Face `json:"face_list,omitempty"`
}

// Face 人脸属性信息
type Face struct {
	FaceToken string `json:"face_token"`
	Location  Location `json:"location"`
	FaceProbability float64 `json:"face_probability"`
	Angle       Angle    `json:"angle"`
	Age         int      `json:"age"`
	Quality     Quality  `json:"quality"`
	EyeStatus   EyeStatus `json:"eye_status"`
	Expression  Expression `json:"expression"`
	FaceShape   FaceShape `json:"face_shape"`
	Gender      Gender    `json:"gender"`
	Race        Race      `json:"race"`
}

// Location 人脸位置信息
type Location struct {
	Left   float64 `json:"left"`
	Top    float64 `json:"top"`
	Width  float64 `json:"width"`
	Height float64 `json:"height"`
	Rotate float64 `json:"rotate"`
}

// Angle 人脸角度信息
type Angle struct {
	Yaw   float64 `json:"yaw"`
	Pitch float64 `json:"pitch"`
	Roll  float64 `json:"roll"`
}

// Quality 人脸质量信息
type Quality struct {
	Occlusion Occlusion `json:"occlusion"`
	Blur      float64   `json:"blur"`
	Illumination int   `json:"illumination"`
	Completeness int   `json:"completeness"`
}

// Occlusion 遮挡信息
type Occlusion struct {
	LeftEye   float64 `json:"left_eye"`
	RightEye  float64 `json:"right_eye"`
	Nose      float64 `json:"nose"`
	Mouth     float64 `json:"mouth"`
	LeftCheek float64 `json:"left_cheek"`
	RightCheek float64 `json:"right_cheek"`
	Chin      float64 `json:"chin"`
}

// EyeStatus 眼部状态信息
type EyeStatus struct {
	LeftEye  float64 `json:"left_eye"`
	RightEye float64 `json:"right_eye"`
}

// Expression 表情信息
type Expression struct {
	Type        string  `json:"type"`
	Probability float64 `json:"probability"`
}

// FaceShape 脸型信息
type FaceShape struct {
	Type        string  `json:"type"`
	Probability float64 `json:"probability"`
}

// Gender 性别信息
type Gender struct {
	Type        string  `json:"type"`
	Probability float64 `json:"probability"`
}

// Race 人种信息
type Race struct {
	Type        string  `json:"type"`
	Probability float64 `json:"probability"`
}

// FaceDetectOptions 人脸检测选项
type FaceDetectOptions struct {
	FaceField    string `json:"face_field,omitempty"`    // 包括哪些属性
	MaxFaceNum   int    `json:"max_face_num,omitempty"`   // 最多检测人脸数
	FaceType     string `json:"face_type,omitempty"`      // 人脸检测类型
	LivenessControl string `json:"liveness_control,omitempty"` // 活体控制
}

// DetectFace 人脸检测与属性分析
// image: 图片数据，base64编码
// imageType: 图片类型，BASE64/URL/FACE_TOKEN
// options: 检测选项
func DetectFace(image, imageType string, options *FaceDetectOptions) (*FaceDetectResponse, error) {
	// 获取访问令牌
	tokenResp, err := GetAccessToken()
	if err != nil {
		return nil, fmt.Errorf("failed to get access token: %v", err)
	}

	// 构建请求参数
	params := url.Values{}
	params.Add("image", image)
	params.Add("image_type", imageType)
	params.Add("access_token", tokenResp.AccessToken)

	// 添加可选参数
	if options != nil {
		if options.FaceField != "" {
			params.Add("face_field", options.FaceField)
		}
		if options.MaxFaceNum > 0 {
			params.Add("max_face_num", fmt.Sprintf("%d", options.MaxFaceNum))
		}
		if options.FaceType != "" {
			params.Add("face_type", options.FaceType)
		}
		if options.LivenessControl != "" {
			params.Add("liveness_control", options.LivenessControl)
		}
	}

	// 创建HTTP客户端
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	// 发送POST请求
	apiURL := "https://aip.baidubce.com/rest/2.0/face/v3/detect"
	resp, err := client.Post(apiURL+"?"+params.Encode(), "application/x-www-form-urlencoded", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to send request: %v", err)
	}
	defer resp.Body.Close()

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}

	// 解析JSON响应
	var detectResp FaceDetectResponse
	err = json.Unmarshal(body, &detectResp)
	if err != nil {
		return nil, fmt.Errorf("failed to parse response JSON: %v", err)
	}

	// 检查错误码
	if detectResp.ErrorCode != 0 {
		return nil, fmt.Errorf("baidu API error: code=%d, msg=%s", detectResp.ErrorCode, detectResp.ErrorMsg)
	}

	return &detectResp, nil
}

// DetectFaceWithJSON 通过JSON格式请求人脸检测
// options: 检测选项
func DetectFaceWithJSON(image, imageType string, options *FaceDetectOptions) (*FaceDetectResponse, error) {
	// 获取访问令牌
	tokenResp, err := GetAccessToken()
	if err != nil {
		return nil, fmt.Errorf("failed to get access token: %v", err)
	}

	// 构建请求参数
	requestData := map[string]interface{}{
		"image":       image,
		"image_type":  imageType,
		"access_token": tokenResp.AccessToken,
	}

	// 添加可选参数
	if options != nil {
		if options.FaceField != "" {
			requestData["face_field"] = options.FaceField
		}
		if options.MaxFaceNum > 0 {
			requestData["max_face_num"] = options.MaxFaceNum
		}
		if options.FaceType != "" {
			requestData["face_type"] = options.FaceType
		}
		if options.LivenessControl != "" {
			requestData["liveness_control"] = options.LivenessControl
		}
	}

	// 将请求数据转换为JSON
	jsonData, err := json.Marshal(requestData)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal request data: %v", err)
	}

	// 创建HTTP客户端
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	// 发送POST请求
	apiURL := "https://aip.baidubce.com/rest/2.0/face/v3/detect"
	req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %v", err)
	}
	req.Header.Set("Content-Type", "application/json")

	q := req.URL.Query()
	q.Add("access_token", tokenResp.AccessToken)
	req.URL.RawQuery = q.Encode()

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to send request: %v", err)
	}
	defer resp.Body.Close()

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}

	// 解析JSON响应
	var detectResp FaceDetectResponse
	err = json.Unmarshal(body, &detectResp)
	if err != nil {
		return nil, fmt.Errorf("failed to parse response JSON: %v", err)
	}

	// 检查错误码
	if detectResp.ErrorCode != 0 {
		return nil, fmt.Errorf("baidu API error: code=%d, msg=%s", detectResp.ErrorCode, detectResp.ErrorMsg)
	}

	return &detectResp, nil
}